package com.alander.nexusgo.im.netty;

import cn.hutool.json.JSONUtil;
import com.alander.nexusgo.im.constants.AppIdEnum;
import com.alander.nexusgo.im.constants.ImConstants;
import com.alander.nexusgo.im.constants.ImMsgCodeEnum;
import com.alander.nexusgo.im.model.dto.ImMsg;
import com.alander.nexusgo.im.model.dto.ImMsgBody;
import com.alander.nexusgo.im.service.TokenService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * IM登录处理器
 */
@Component
public class ImLoginHandler extends SimpleChannelInboundHandler<ImMsg> {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(ImLoginHandler.class);
    
    @Autowired
    private TokenService tokenService;
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ImMsg msg) throws Exception {
        // 只处理登录消息
        if (msg.getCode() == ImMsgCodeEnum.IM_LOGIN_MSG.getCode()) {
            handleLogin(ctx, msg);
        } else {
            // 将消息传递给下一个处理器
            ctx.fireChannelRead(msg);
        }
    }
    
    /**
     * 处理登录消息
     * @param ctx 通道上下文
     * @param msg 消息
     */
    private void handleLogin(ChannelHandlerContext ctx, ImMsg msg) {
        try {
            // 解析消息体
            String bodyJson = new String(msg.getBody());
            ImMsgBody msgBody = JSONUtil.toBean(bodyJson, ImMsgBody.class);
            
            // 验证token
            Long userId = tokenService.getUserIdByToken(msgBody.getToken());
            if (userId == null || !userId.equals(msgBody.getUserId())) {
                LOGGER.warn("无效的token或用户ID不匹配: userId={}, token={}", msgBody.getUserId(), msgBody.getToken());
                ctx.close();
                return;
            }
            
            // 将用户ID和appId附加到通道属性中
            ctx.channel().attr(ImServerAttributes.USER_ID).set(userId);
            ctx.channel().attr(ImServerAttributes.APP_ID).set(msgBody.getAppId());
            
            // 根据应用类型添加到相应的连接管理器中
            if (msgBody.getAppId() == AppIdEnum.GROUP_CHAT.getCode()) {
                // 群聊应用，添加到聊天室连接管理器
                ImConnectionManager.addChatRoomMember((int) (msgBody.getBizCode()), ctx.channel());
            } else if (msgBody.getAppId() == AppIdEnum.SINGLE_CHAT.getCode()) {
                // 单聊应用，添加到用户连接管理器
                ImConnectionManager.addUserChannel(userId, ctx.channel());
            }
            
            LOGGER.info("用户登录成功: userId={}, appId={}", userId, msgBody.getAppId());
            
            // 发送登录成功的响应
            ImMsg response = new ImMsg();
            response.setMagic(ImConstants.DEFAULT_MAGIC);
            response.setCode(ImMsgCodeEnum.IM_ACK_MSG.getCode());
            response.setLen(0);
            response.setBody(new byte[0]);
            
            ctx.writeAndFlush(response);
        } catch (Exception e) {
            LOGGER.error("处理登录消息时发生错误", e);
            ctx.close();
        }
    }
    
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                LOGGER.info("连接超时，关闭连接: {}", ctx.channel().remoteAddress());
                ctx.close();
            }
        }
        super.userEventTriggered(ctx, evt);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        LOGGER.error("连接异常: {}", ctx.channel().remoteAddress(), cause);
        ctx.close();
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 连接断开时清理资源
        Channel channel = ctx.channel();
        Long userId = channel.attr(ImServerAttributes.USER_ID).get();
        Integer appId = channel.attr(ImServerAttributes.APP_ID).get();
        
        if (userId != null && appId != null) {
            if (appId == AppIdEnum.GROUP_CHAT.getCode()) {
                // 从聊天室连接管理器中移除
                // 注意：这里需要知道用户在哪个聊天室，可以通过其他方式记录
                LOGGER.info("用户断开群聊连接: userId={}", userId);
            } else if (appId == AppIdEnum.SINGLE_CHAT.getCode()) {
                // 从用户连接管理器中移除
                ImConnectionManager.removeUserChannel(userId);
                LOGGER.info("用户断开单聊连接: userId={}", userId);
            }
        }
        
        super.channelInactive(ctx);
    }
}